﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Elasticsearch.Net;

namespace Nest
{
	[MapsApi("watcher.execute_watch.json")]
	public partial interface IExecuteWatchRequest
	{
		/// <summary>
		/// Determines how to handle the watch actions as part of the watch execution.
		/// </summary>
		[DataMember(Name = "action_modes")]
		[JsonFormatter(typeof(VerbatimDictionaryInterfaceKeysFormatter<string, ActionExecutionMode>))]
		IDictionary<string, ActionExecutionMode> ActionModes { get; set; }

		/// <summary>
		/// When present, the watch uses this object as a payload
		/// instead of executing its own input.
		/// </summary>
		[DataMember(Name = "alternative_input")]
		[JsonFormatter(typeof(VerbatimDictionaryInterfaceKeysFormatter<string, object>))]
		IDictionary<string, object> AlternativeInput { get; set; }

		/// <summary>
		/// If this is set to true the watch execution will use the Always Condition.
		/// </summary>
		[DataMember(Name = "ignore_condition")]
		bool? IgnoreCondition { get; set; }

		/// <summary>
		/// If this is set to true the WatchRecord generated by executing the watch will be persisted
		/// to the .watcher_history index for the current time.
		/// Also the status of the watch is updated,
		/// possbily throttling subsequent executions.
		/// </summary>
		[DataMember(Name = "record_execution")]
		bool? RecordExecution { get; set; }

		/// <summary>
		/// This field can either be a list of action ids or the string _all.
		///  If _all is set or an action that is executed by the watch appears in this list
		///  it will be executed in simulated mode.
		/// </summary>
		[DataMember(Name = "simulated_actions")]
		SimulatedActions SimulatedActions { get; set; }

		/// <summary>
		/// This structure will be parsed as a trigger event and used for the watch execution.
		/// </summary>
		[DataMember(Name = "trigger_data")]
		IScheduleTriggerEvent TriggerData { get; set; }

		/// <summary>
		/// When present, this watch is used instead of the one specified in the request.
		/// This watch is not persisted to the index and record_execution cannot be set.
		/// </summary>
		[DataMember(Name = "watch")]
		IWatch Watch { get; set; }
	}

	public partial class ExecuteWatchRequest
	{
		public IDictionary<string, ActionExecutionMode> ActionModes { get; set; }

		public IDictionary<string, object> AlternativeInput { get; set; }

		public bool? IgnoreCondition { get; set; }

		public bool? RecordExecution { get; set; }

		public SimulatedActions SimulatedActions { get; set; }
		public IScheduleTriggerEvent TriggerData { get; set; }

		public IWatch Watch { get; set; }
	}

	public partial class ExecuteWatchDescriptor
	{
		IDictionary<string, ActionExecutionMode> IExecuteWatchRequest.ActionModes { get; set; }
		IDictionary<string, object> IExecuteWatchRequest.AlternativeInput { get; set; }
		bool? IExecuteWatchRequest.IgnoreCondition { get; set; }
		bool? IExecuteWatchRequest.RecordExecution { get; set; }
		SimulatedActions IExecuteWatchRequest.SimulatedActions { get; set; }
		IScheduleTriggerEvent IExecuteWatchRequest.TriggerData { get; set; }
		IWatch IExecuteWatchRequest.Watch { get; set; }

		public ExecuteWatchDescriptor TriggerData(Func<ScheduleTriggerEventDescriptor, IScheduleTriggerEvent> selector) =>
			Assign(selector, (a, v) => a.TriggerData = v?.InvokeOrDefault(new ScheduleTriggerEventDescriptor()));

		public ExecuteWatchDescriptor IgnoreCondition(bool? ignore = true) =>
			Assign(ignore, (a, v) => a.IgnoreCondition = v);

		public ExecuteWatchDescriptor RecordExecution(bool? record = true) =>
			Assign(record, (a, v) => a.RecordExecution = v);

		public ExecuteWatchDescriptor ActionModes(
			Func<FluentDictionary<string, ActionExecutionMode>, FluentDictionary<string, ActionExecutionMode>> actionModesDictionary
		) =>
			Assign(actionModesDictionary(new FluentDictionary<string, ActionExecutionMode>()), (a, v) => a.ActionModes = v);

		public ExecuteWatchDescriptor ActionModes(Dictionary<string, ActionExecutionMode> actionModesDictionary) =>
			Assign(actionModesDictionary, (a, v) => a.ActionModes = v);

		public ExecuteWatchDescriptor AlternativeInput(
			Func<FluentDictionary<string, object>, FluentDictionary<string, object>> alternativeInputDictionary
		) =>
			Assign(alternativeInputDictionary(new FluentDictionary<string, object>()), (a, v) => a.AlternativeInput = v);

		public ExecuteWatchDescriptor AlternativeInput(Dictionary<string, object> alternativeInputDictionary) =>
			Assign(alternativeInputDictionary, (a, v) => a.AlternativeInput = v);

		public ExecuteWatchDescriptor SimulatedActions(SimulatedActions simulatedActions) =>
			Assign(simulatedActions, (a, v) => a.SimulatedActions = v);

		public ExecuteWatchDescriptor Watch(Func<WatchDescriptor, IWatch> watch) =>
			Assign(watch, (a, v) => a.Watch = v?.InvokeOrDefault(new WatchDescriptor()));
	}
}
